<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
	<title>分析与分析器 | Elasticsearch: 权威指南 | Elastic</title>
    <!-- Give IE8 a fighting chance -->
    <!--[if lt IE 9]>
    <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
    <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
    <![endif]-->
	<link rel="stylesheet" type="text/css" href="../static/styles.css" />
</head>
<body>
<div class="main-container">
    <section id="content">
        
        <div class="content-wrapper">
            <section id="guide" lang="zh_cn">
                <div class="container">
                    <div class="row">
                        <div class="col-xs-12 col-sm-8 col-md-8 guide-section">
                            <div style="color:gray; word-break: break-all; font-size:12px;">原文地址: <a href="https://www.elastic.co/guide/cn/elasticsearch/guide/current/analysis-intro.html" rel="nofollow">https://www.elastic.co/guide/cn/elasticsearch/guide/current/analysis-intro.html</a>, 版权归 www.elastic.co 所有<br/>
                            英文版地址: <a href="https://www.elastic.co/guide/en/elasticsearch/guide/current/analysis-intro.html" rel="nofollow">https://www.elastic.co/guide/en/elasticsearch/guide/current/analysis-intro.html</a>
                            </div>
                        <!-- start body -->
                  <div class="page_header">
<b>请注意:</b><br>本书基于 Elasticsearch 2.x 版本，有些内容可能已经过时。
</div>
<div id="content">
<div class="breadcrumbs">
<span class="breadcrumb-link"><a href="index.html">Elasticsearch: 权威指南</a></span>
»
<span class="breadcrumb-link"><a href="getting-started.html">基础入门</a></span>
»
<span class="breadcrumb-link"><a href="mapping-analysis.html">映射和分析</a></span>
»
<span class="breadcrumb-node">分析与分析器</span>
</div>
<div class="navheader">
<span class="prev">
<a href="inverted-index.html">« 倒排索引</a>
</span>
<span class="next">
<a href="mapping-intro.html">映射 »</a>
</span>
</div>
<div class="section pagebreak-before">
<div class="titlepage"><div><div>
<h2 class="title">
<a id="analysis-intro"></a>分析与分析器<a class="edit_me edit_me_private" rel="nofollow" title="Editing on GitHub is available to Elastic" href="https://github.com/elasticsearch-cn/elasticsearch-definitive-guide/edit/cn/052_Mapping_Analysis/40_Analysis.asciidoc">edit</a>
</h2>
</div></div></div>
<p><em>分析</em> 包含下面的过程：</p>
<div class="ulist itemizedlist">
<ul class="itemizedlist">
<li class="listitem">
首先，将一块文本分成适合于倒排索引的独立的 <em>词条</em> ，
</li>
<li class="listitem">
之后，将这些词条统一化为标准格式以提高它们的“可搜索性”，或者 <em>recall</em>
</li>
</ul>
</div>
<p>分析器执行上面的工作。 <em>分析器</em> 实际上是将三个功能封装到了一个包里：</p>
<div class="variablelist">
<dl class="variablelist">
<dt>
<span class="term">
字符过滤器
</span>
</dt>
<dd>
首先，字符串按顺序通过每个 <em>字符过滤器</em> 。他们的任务是在分词前整理字符串。一个字符过滤器可以用来去掉HTML，或者将 <code class="literal">&amp;</code> 转化成 <code class="literal">and</code>。
</dd>
<dt>
<span class="term">
分词器
</span>
</dt>
<dd>
其次，字符串被 <em>分词器</em> 分为单个的词条。一个简单的分词器遇到空格和标点的时候，可能会将文本拆分成词条。
</dd>
<dt>
<span class="term">
Token 过滤器
</span>
</dt>
<dd>
最后，词条按顺序通过每个 <em>token 过滤器</em> 。这个过程可能会改变词条（例如，小写化 <code class="literal">Quick</code> ），删除词条（例如， 像 <code class="literal">a</code>， <code class="literal">and</code>， <code class="literal">the</code> 等无用词），或者增加词条（例如，像 <code class="literal">jump</code> 和 <code class="literal">leap</code> 这种同义词）。
</dd>
</dl>
</div>
<p>Elasticsearch提供了开箱即用的字符过滤器、分词器和token 过滤器。 这些可以组合起来形成自定义的分析器以用于不同的目的。我们会在 <a class="xref" href="custom-analyzers.html" title="自定义分析器">自定义分析器</a> 章节详细讨论。</p>
<div class="section">
<div class="titlepage"><div><div>
<h3 class="title">
<a id="_内置分析器"></a>内置分析器<a class="edit_me edit_me_private" rel="nofollow" title="Editing on GitHub is available to Elastic" href="https://github.com/elasticsearch-cn/elasticsearch-definitive-guide/edit/cn/052_Mapping_Analysis/40_Analysis.asciidoc">edit</a>
</h3>
</div></div></div>
<p>但是， Elasticsearch还附带了可以直接使用的预包装的分析器。接下来我们会列出最重要的分析器。为了证明它们的差异，我们看看每个分析器会从下面的字符串得到哪些词条：</p>
<pre class="literallayout">"Set the shape to semi-transparent by calling set_trans(5)"</pre>

<div class="variablelist">
<dl class="variablelist">
<dt>
<span class="term">
标准分析器
</span>
</dt>
<dd>
<p>
标准分析器是Elasticsearch默认使用的分析器。它是分析各种语言文本最常用的选择。它根据 <a href="http://www.unicode.org/reports/tr29/" class="ulink" target="_top">Unicode 联盟</a> 定义的 <em>单词边界</em> 划分文本。删除绝大部分标点。最后，将词条小写。它会产生
</p>
<pre class="literallayout">set, the, shape, to, semi, transparent, by, calling, set_trans, 5</pre>

</dd>
<dt>
<span class="term">
简单分析器
</span>
</dt>
<dd>
<p>
简单分析器在任何不是字母的地方分隔文本，将词条小写。它会产生
</p>
<pre class="literallayout">set, the, shape, to, semi, transparent, by, calling, set, trans</pre>

</dd>
<dt>
<span class="term">
空格分析器
</span>
</dt>
<dd>
<p>
空格分析器在空格的地方划分文本。它会产生
</p>
<pre class="literallayout">Set, the, shape, to, semi-transparent, by, calling, set_trans(5)</pre>

</dd>
<dt>
<span class="term">
语言分析器
</span>
</dt>
<dd>
<p>
特定语言分析器可用于 <a href="https://www.elastic.co/guide/en/elasticsearch/reference/5.6/analysis-lang-analyzer.html" class="ulink" target="_top">很多语言</a>。它们可以考虑指定语言的特点。例如， <code class="literal">英语</code> 分析器附带了一组英语无用词（常用单词，例如 <code class="literal">and</code> 或者 <code class="literal">the</code> ，它们对相关性没有多少影响），它们会被删除。 由于理解英语语法的规则，这个分词器可以提取英语单词的 <em>词干</em> 。
</p>
<p><code class="literal">英语</code> 分词器会产生下面的词条：</p>
<pre class="literallayout">set, shape, semi, transpar, call, set_tran, 5</pre>

<p>注意看 <code class="literal">transparent</code>、 <code class="literal">calling</code> 和 <code class="literal">set_trans</code> 已经变为词根格式。</p>
</dd>
</dl>
</div>
</div>

<div class="section">
<div class="titlepage"><div><div>
<h3 class="title">
<a id="_什么时候使用分析器"></a>什么时候使用分析器<a class="edit_me edit_me_private" rel="nofollow" title="Editing on GitHub is available to Elastic" href="https://github.com/elasticsearch-cn/elasticsearch-definitive-guide/edit/cn/052_Mapping_Analysis/40_Analysis.asciidoc">edit</a>
</h3>
</div></div></div>
<p>当我们 <em>索引</em> 一个文档，它的全文域被分析成词条以用来创建倒排索引。  但是，当我们在全文域 <em>搜索</em> 的时候，我们需要将查询字符串通过 <em>相同的分析过程</em> ，以保证我们搜索的词条格式与索引中的词条格式一致。</p>
<p>全文查询，理解每个域是如何定义的，因此它们可以做正确的事：</p>
<div class="ulist itemizedlist">
<ul class="itemizedlist">
<li class="listitem">
当你查询一个 <em>全文</em> 域时， 会对查询字符串应用相同的分析器，以产生正确的搜索词条列表。
</li>
<li class="listitem">
当你查询一个 <em>精确值</em> 域时，不会分析查询字符串，而是搜索你指定的精确值。
</li>
</ul>
</div>
<p>现在你可以理解在 <a class="xref" href="mapping-analysis.html" title="映射和分析">开始章节</a> 的查询为什么返回那样的结果：</p>
<div class="ulist itemizedlist">
<ul class="itemizedlist">
<li class="listitem">
<code class="literal">date</code> 域包含一个精确值：单独的词条 <code class="literal">2014-09-15</code>。
</li>
<li class="listitem">
<code class="literal">_all</code> 域是一个全文域，所以分词进程将日期转化为三个词条： <code class="literal">2014</code>， <code class="literal">09</code>， 和 <code class="literal">15</code>。
</li>
</ul>
</div>
<p>当我们在 <code class="literal">_all</code> 域查询 <code class="literal">2014</code>，它匹配所有的12条推文，因为它们都含有 <code class="literal">2014</code> ：</p>
<div class="pre_wrapper lang-sense">
<pre class="programlisting prettyprint lang-sense">GET /_search?q=2014              # 12 results</pre>
</div>
<div class="sense_widget" data-snippet="snippets/052_Mapping_Analysis/25_Data_type_differences.json"></div>
<p>当我们在 <code class="literal">_all</code> 域查询 <code class="literal">2014-09-15</code>，它首先分析查询字符串，产生匹配 <code class="literal">2014</code>， <code class="literal">09</code>， 或 <code class="literal">15</code> 中 <em>任意</em> 词条的查询。这也会匹配所有12条推文，因为它们都含有 <code class="literal">2014</code> ：</p>
<div class="pre_wrapper lang-sense">
<pre class="programlisting prettyprint lang-sense">GET /_search?q=2014-09-15        # 12 results !</pre>
</div>
<div class="sense_widget" data-snippet="snippets/052_Mapping_Analysis/25_Data_type_differences.json"></div>
<p>当我们在 <code class="literal">date</code> 域查询 <code class="literal">2014-09-15</code>，它寻找 <em>精确</em>
日期，只找到一个推文：</p>
<div class="pre_wrapper lang-sense">
<pre class="programlisting prettyprint lang-sense">GET /_search?q=date:2014-09-15   # 1  result</pre>
</div>
<div class="sense_widget" data-snippet="snippets/052_Mapping_Analysis/25_Data_type_differences.json"></div>
<p>当我们在 <code class="literal">date</code> 域查询 <code class="literal">2014</code>，它找不到任何文档，因为没有文档含有这个精确日志：</p>
<div class="pre_wrapper lang-sense">
<pre class="programlisting prettyprint lang-sense">GET /_search?q=date:2014         # 0  results !</pre>
</div>
<div class="sense_widget" data-snippet="snippets/052_Mapping_Analysis/25_Data_type_differences.json"></div>
</div>

<div class="section">
<div class="titlepage"><div><div>
<h3 class="title">
<a id="analyze-api"></a>测试分析器<a class="edit_me edit_me_private" rel="nofollow" title="Editing on GitHub is available to Elastic" href="https://github.com/elasticsearch-cn/elasticsearch-definitive-guide/edit/cn/052_Mapping_Analysis/40_Analysis.asciidoc">edit</a>
</h3>
</div></div></div>
<p>有些时候很难理解分词的过程和实际被存储到索引中的词条，特别是你刚接触Elasticsearch。为了理解发生了什么，你可以使用 <code class="literal">analyze</code> API 来看文本是如何被分析的。在消息体里，指定分析器和要分析的文本：</p>
<div class="pre_wrapper lang-sense">
<pre class="programlisting prettyprint lang-sense">GET /_analyze
{
  "analyzer": "standard",
  "text": "Text to analyze"
}</pre>
</div>
<div class="sense_widget" data-snippet="snippets/052_Mapping_Analysis/40_Analyze.json"></div>
<p>结果中每个元素代表一个单独的词条：</p>
<div class="pre_wrapper lang-js">
<pre class="programlisting prettyprint lang-js">{
   "tokens": [
      {
         "token":        "text",
         "start_offset": 0,
         "end_offset":   4,
         "type":         "&lt;ALPHANUM&gt;",
         "position":     1
      },
      {
         "token":        "to",
         "start_offset": 5,
         "end_offset":   7,
         "type":         "&lt;ALPHANUM&gt;",
         "position":     2
      },
      {
         "token":        "analyze",
         "start_offset": 8,
         "end_offset":   15,
         "type":         "&lt;ALPHANUM&gt;",
         "position":     3
      }
   ]
}</pre>
</div>
<p><code class="literal">token</code> 是实际存储到索引中的词条。 <code class="literal">position</code> 指明词条在原始文本中出现的位置。 <code class="literal">start_offset</code> 和 <code class="literal">end_offset</code> 指明字符在原始字符串中的位置。</p>
<div class="tip admon">
<div class="icon"></div>
<div class="admon_content">
<p>每个分析器的 <code class="literal">type</code> 值都不一样，可以忽略它们。它们在Elasticsearch中的唯一作用在于​<a href="https://www.elastic.co/guide/en/elasticsearch/reference/5.6/analysis-keep-types-tokenfilter.html" class="ulink" target="_top"><code class="literal">keep_types</code> token 过滤器</a>​。</p>
</div>
</div>
<p><code class="literal">analyze</code> API 是一个有用的工具，它有助于我们理解Elasticsearch索引内部发生了什么，随着深入，我们会进一步讨论它。</p>
</div>

<div class="section">
<div class="titlepage"><div><div>
<h3 class="title">
<a id="_指定分析器"></a>指定分析器<a class="edit_me edit_me_private" rel="nofollow" title="Editing on GitHub is available to Elastic" href="https://github.com/elasticsearch-cn/elasticsearch-definitive-guide/edit/cn/052_Mapping_Analysis/40_Analysis.asciidoc">edit</a>
</h3>
</div></div></div>
<p>当Elasticsearch在你的文档中检测到一个新的字符串域，它会自动设置其为一个全文 <code class="literal">字符串</code> 域，使用 <code class="literal">标准</code> 分析器对它进行分析。</p>
<p>你不希望总是这样。可能你想使用一个不同的分析器，适用于你的数据使用的语言。有时候你想要一个字符串域就是一个字符串域—​不使用分析，直接索引你传入的精确值，例如用户ID或者一个内部的状态域或标签。</p>
<p>要做到这一点，我们必须手动指定这些域的映射。</p>
</div>

</div>
<div class="navfooter">
<span class="prev">
<a href="inverted-index.html">« 倒排索引</a>
</span>
<span class="next">
<a href="mapping-intro.html">映射 »</a>
</span>
</div>
</div>

                  <!-- end body -->
                        </div>
                        <div class="col-xs-12 col-sm-4 col-md-4" id="right_col">
                        
                        </div>
                    </div>
                </div>
            </section>
        </div>
    </section>
</div>
<script src="../static/cn.js"></script>
</body>
</html>